home *** CD-ROM | disk | FTP | other *** search
Oberon Text | 1994-07-11 | 7.5 KB | 207 lines | [.Ob./.Ob4] |
- Syntax10.Scn.Fnt
- Syntax10i.Scn.Fnt
- MODULE ClockElems; (* gri 18.3.91 / 28.9.93 *)
- IMPORT Texts, TextFrames, TextPrinter, Math, Oberon, Display, Printer, Viewers, Files;
- CONST
- ticks = 300; (* Oberon.Time ticks per second *)
- Rmin = 12; (* minimal clock radius in pixels *)
- Rdef = 8.2; (* default clock radius in mm *)
- TYPE
- Time = RECORD sec, min, hour, hourm: INTEGER; timeStamp, dateStamp: LONGINT END;
- Frame = POINTER TO RECORD(Display.FrameDesc) col: SHORTINT END;
- NotifyMsg = RECORD(Display.FrameMsg) new: Time END;
- sin, cos: ARRAY 60 OF REAL;
- wakeUp: LONGINT; (* overflow in 82.8 days *)
- old: Time; (* displayed time *)
- Task: Oberon.Task;
- Line: PROCEDURE(x1, y1, x2, y2, color, mode: INTEGER); (* current output procedure *)
- Circle: PROCEDURE(x0, y0, r, color, mode: INTEGER); (* current output procedure *)
- (* initialization *)
- PROCEDURE Init;
- VAR i: INTEGER;
- BEGIN i := 0;
- WHILE i < 60 DO
- sin[i] := Math.sin(2 * Math.pi / 60 * i);
- cos[i] := Math.cos(2 * Math.pi / 60 * i);
- INC(i)
- END
- END Init;
- PROCEDURE GetTime(VAR time: Time);
- VAR t: LONGINT;
- BEGIN
- Oberon.GetClock(time.timeStamp, time.dateStamp);
- t := time.timeStamp;
- time.sec := SHORT(t MOD 64);
- time.min := SHORT(t DIV 64 MOD 64);
- time.hour := SHORT(t DIV (64*64) MOD 32);
- time.hourm := (time.hour MOD 12)*5 + time.min DIV 12;
- time.timeStamp := t
- END GetTime;
- PROCEDURE SetTime(VAR time: Time);
- VAR t: LONGINT;
- BEGIN
- t := (LONG(time.hour)*64 + time.min)*64 + time.sec;
- Oberon.SetClock(t, time.dateStamp)
- END SetTime;
- (* graphics *)
- PROCEDURE SCircle(x0, y0, r, color, mode: INTEGER);
- VAR x, y, dx, dy, d: INTEGER;
- PROCEDURE Dot4(x1, x2, y1, y2, color, mode: INTEGER);
- BEGIN
- Display.Dot(color, x1, y1, mode);
- Display.Dot(color, x1, y2, mode);
- Display.Dot(color, x2, y1, mode);
- Display.Dot(color, x2, y2, mode)
- END Dot4;
- BEGIN
- x := r; y := 0; dx := 8*(x-1); dy := 8*y+4; d := 1-4*r;
- WHILE x > y DO
- Dot4(x0-x, x0+x, y0-y, y0+y, color, mode);
- Dot4(x0-y, x0+y, y0-x, y0+x, color, mode);
- INC(d, dy); INC(dy, 8); INC(y);
- IF d >= 0 THEN DEC(d, dx); DEC(dx, 8); DEC(x) END
- END;
- IF x = y THEN Dot4(x0-x, x0+x, y0-y, y0+y, color, mode) END
- END SCircle;
- PROCEDURE SLine(x1, y1, x2, y2, color, mode: INTEGER);
- VAR x, y, dx, dy, d, inc: INTEGER;
- BEGIN
- IF (y2-y1) < (x1-x2) THEN x := x1; x1 := x2; x2 := x; y := y1; y1 := y2; y2 := y END;
- dx := 2*(x2-x1);
- dy := 2*(y2-y1);
- x := x1; y := y1; inc := 1;
- IF dy > dx THEN
- d := dy DIV 2;
- IF dx < 0 THEN inc := -1; dx := -dx END;
- WHILE y <= y2 DO
- Display.Dot(color, x, y, mode);
- INC(y); DEC(d, dx);
- IF d < 0 THEN INC(d, dy); INC(x, inc) END
- END
- ELSE
- d := dx DIV 2;
- IF dy < 0 THEN inc := -1; dy := -dy END;
- WHILE x <= x2 DO
- Display.Dot(color, x, y, mode);
- INC(x); DEC(d, dy);
- IF d < 0 THEN INC(d, dx); INC(y, inc) END
- END
- END
- END SLine;
- PROCEDURE PCircle(x0, y0, r, color, mode: INTEGER);
- BEGIN Printer.Circle(x0, y0, r)
- END PCircle;
- PROCEDURE PLine(x1, y1, x2, y2, color, mode: INTEGER);
- BEGIN Printer.Line(x1, y1, x2, y2)
- END PLine;
- (* view update *)
- PROCEDURE Line2(ang: INTEGER; x0, y0, r1, r2, color: INTEGER);
- VAR x1, y1, x2, y2: INTEGER;
- BEGIN
- ang := (15-ang) MOD 60;
- x1 := SHORT(ENTIER(r1*cos[ang] + 0.5));
- y1 := SHORT(ENTIER(r1*sin[ang] + 0.5));
- x2 := SHORT(ENTIER(r2*cos[ang] + 0.5));
- y2 := SHORT(ENTIER(r2*sin[ang] + 0.5));
- Line(x0+x1, y0+y1, x0+x2, y0+y2, color, Display.invert)
- END Line2;
- PROCEDURE Draw(VAR time: Time; x0, y0, r, color: INTEGER);
- VAR rh, rm, rs, i: INTEGER;
- BEGIN
- IF r >= Rmin THEN
- rh := 7*r DIV 11; rm := 9*r DIV 11; rs := 10*r DIV 11; i := 0;
- WHILE i < 60 DO Line2(i, x0, y0, rm, r, color); INC(i, 5) END;
- Line2(time.sec, x0, y0, rm-r, rs, color);
- Line2(time.min, x0, y0, 0, rm, color);
- Line2(time.hourm, x0, y0, 0, rh, color);
- Circle(x0, y0, 2, color, Display.replace)
- END;
- Circle(x0, y0, r, color, Display.replace)
- END Draw;
- PROCEDURE Update(VAR old, new: Time; x0, y0, r, color: INTEGER);
- VAR rh, rm, rs: INTEGER;
- BEGIN
- IF r >= Rmin THEN
- rh := 7*r DIV 11; rm := 9*r DIV 11; rs := 10*r DIV 11;
- IF old.sec # new.sec THEN Line2(old.sec, x0, y0, rm-r, rs, color); Line2(new.sec, x0, y0, rm-r, rs, color) END;
- IF old.min # new.min THEN Line2(old.min, x0, y0, 0, rm, color); Line2(new.min, x0, y0, 0, rm, color) END;
- IF old.hourm # new.hourm THEN Line2(old.hourm, x0, y0, 0, rh, color); Line2(new.hourm, x0, y0, 0, rh, color) END;
- END
- END Update;
- (* methods *)
- PROCEDURE HandleFrame(F: Display.Frame; VAR msg: Display.FrameMsg);
- VAR r: INTEGER; V: Viewers.Viewer; ch: CHAR; new: Time;
- BEGIN
- IF msg IS NotifyMsg THEN Line := SLine; Circle := SCircle; r := F.W DIV 2;
- Update(old, msg(NotifyMsg).new, F.X+r, F.Y+r, r, F(Frame).col)
- ELSIF msg IS Oberon.InputMsg THEN
- WITH msg: Oberon.InputMsg DO
- IF msg.id = Oberon.track THEN Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, msg.X, msg.Y) END
- END
- END
- END HandleFrame;
- PROCEDURE HandleElem(E: Texts.Elem; VAR msg: Texts.ElemMsg);
- VAR CopyOfE: Texts.Elem; F: Frame; r: INTEGER; ch: CHAR;
- BEGIN
- IF msg IS TextFrames.DisplayMsg THEN
- WITH msg: TextFrames.DisplayMsg DO
- IF ~msg.prepare THEN
- Line := SLine; Circle := SCircle; r := SHORT((E.W DIV TextFrames.Unit - 1) DIV 2);
- Draw(old, msg.X0+r, msg.Y0+r, r, msg.col);
- NEW(F); F.X := msg.X0; F.Y := msg.Y0; F.W := 2*r + 1; F.H := F.W;
- F.handle := HandleFrame; F.col := msg.col;
- msg.elemFrame := F
- END
- END
- ELSIF msg IS TextPrinter.PrintMsg THEN
- WITH msg: TextPrinter.PrintMsg DO
- IF ~msg.prepare THEN
- Line := PLine; Circle := PCircle; r := SHORT((E.W DIV TextPrinter.Unit - 1) DIV 2);
- Draw(old, msg.X0+r, msg.Y0+r, r, msg.col)
- END
- END
- ELSIF msg IS Texts.CopyMsg THEN
- NEW(CopyOfE); Texts.CopyElem(E, CopyOfE); msg(Texts.CopyMsg).e := CopyOfE
- ELSIF msg IS Texts.IdentifyMsg THEN
- WITH msg: Texts.IdentifyMsg DO
- msg.mod := "ClockElems"; msg.proc := "New"
- END
- ELSIF msg IS Texts.FileMsg THEN
- WITH msg: Texts.FileMsg DO
- IF msg.id = Texts.load THEN Files.Read(msg.r, ch) (* ignore in this version *)
- ELSIF msg.id = Texts.store THEN Files.Write(msg.r, 0X); (* version tag: used for future extensions *)
- END
- END
- END
- END HandleElem;
- PROCEDURE* Clock;
- VAR msg: NotifyMsg;
- BEGIN
- IF Oberon.Time() >= wakeUp THEN GetTime(msg.new);
- IF msg.new.timeStamp # old.timeStamp THEN wakeUp := Oberon.Time() + ticks * 15 DIV 16;
- Viewers.Broadcast(msg); old := msg.new
- ELSE wakeUp := Oberon.Time() + ticks DIV 16 (* synchronization *)
- END
- END
- END Clock;
- (* commands *)
- PROCEDURE New*;
- BEGIN NEW(Texts.new); Texts.new.handle := HandleElem
- END New;
- PROCEDURE Insert*;
- VAR S: Texts.Scanner; r: REAL; w: LONGINT; E: Texts.Elem; m: TextFrames.InsertElemMsg;
- BEGIN
- Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
- IF (S.line = 0) & (S.class = Texts.Int) & (S.i > 0) THEN r := S.i
- ELSIF (S.line = 0) & (S.class = Texts.Real) & (S.x > 0) THEN r := S.x
- ELSE r := Rdef
- END;
- w := ENTIER(2*TextFrames.mm*r);
- NEW(E); E.W := w; E.H := w; E.handle := HandleElem; m.e := E;
- Oberon.FocusViewer.handle(Oberon.FocusViewer, m)
- END Insert;
- BEGIN
- Init; wakeUp := 0; GetTime(old);
- NEW(Task); Task.safe := FALSE; Task.handle := Clock; Oberon.Install(Task)
- END ClockElems.
-